home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / Tcl-Tk 8.0 / Pre-installed version / tk8.0 / mac / tkMacSend.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-15  |  12.5 KB  |  359 lines  |  [TEXT/CWIE]

  1. /* 
  2.  * tkMacSend.c --
  3.  *
  4.  *    This file provides procedures that implement the "send"
  5.  *    command, allowing commands to be passed from interpreter
  6.  *    to interpreter.  This current implementation for the Mac
  7.  *    has most functionality stubed out.
  8.  *
  9.  * Copyright (c) 1989-1994 The Regents of the University of California.
  10.  * Copyright (c) 1994-1996 Sun Microsystems, Inc.
  11.  *
  12.  * See the file "license.terms" for information on usage and redistribution
  13.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  14.  *
  15.  * SCCS: @(#) tkMacSend.c 1.7 96/12/03 11:48:27
  16.  */
  17.  
  18. #include "tkPort.h"
  19. #include "tkInt.h"
  20.  
  21.      /* 
  22.       * The following structure is used to keep track of the
  23.       * interpreters registered by this process.
  24.       */
  25.  
  26. typedef struct RegisteredInterp {
  27.     char *name;            /* Interpreter's name (malloc-ed). */
  28.     Tcl_Interp *interp;        /* Interpreter associated with
  29.                  * name. */
  30.     TkWindow *winPtr;        /* Main window for the application. */
  31.     struct RegisteredInterp *nextPtr;
  32.     /* Next in list of names associated
  33.      * with interps in this process.
  34.      * NULL means end of list. */
  35. } RegisteredInterp;
  36.  
  37. static RegisteredInterp *registry = NULL;
  38. /* List of all interpreters
  39.  * registered by this process. */
  40.  
  41. /*
  42.  * A registry of all interpreters for a display is kept in a
  43.  * property "InterpRegistry" on the root window of the display.
  44.  * It is organized as a series of zero or more concatenated strings
  45.  * (in no particular order), each of the form
  46.  *     window space name '\0'
  47.  * where "window" is the hex id of the comm. window to use to talk
  48.  * to an interpreter named "name".
  49.  *
  50.  * When the registry is being manipulated by an application (e.g. to
  51.  * add or remove an entry), it is loaded into memory using a structure
  52.  * of the following type:
  53.  */
  54.  
  55. typedef struct NameRegistry {
  56.     TkDisplay *dispPtr;        /* Display from which the registry was
  57.                  * read. */
  58.     int locked;            /* Non-zero means that the display was
  59.                  * locked when the property was read in. */
  60.     int modified;        /* Non-zero means that the property has
  61.                  * been modified, so it needs to be written
  62.                  * out when the NameRegistry is closed. */
  63.     unsigned long propLength;    /* Length of the property, in bytes. */
  64.     char *property;        /* The contents of the property.  See format
  65.                  * above;  this is *not* terminated by the
  66.                  * first null character.  Dynamically
  67.                  * allocated. */
  68.     int allocedByX;        /* Non-zero means must free property with
  69.                  * XFree;  zero means use ckfree. */
  70. } NameRegistry;
  71.  
  72.      /*
  73.       * When a result is being awaited from a sent command, one of
  74.       * the following structures is present on a list of all outstanding
  75.       * sent commands.  The information in the structure is used to
  76.       * process the result when it arrives.  You're probably wondering
  77.       * how there could ever be multiple outstanding sent commands.
  78.       * This could happen if interpreters invoke each other recursively.
  79.       * It's unlikely, but possible.
  80.       */
  81.  
  82. typedef struct PendingCommand {
  83.     int serial;            /* Serial number expected in
  84.                  * result. */
  85.     TkDisplay *dispPtr;        /* Display being used for communication. */
  86.     char *target;        /* Name of interpreter command is
  87.                  * being sent to. */
  88.     Window commWindow;        /* Target's communication window. */
  89.     Tk_TimerToken timeout;    /* Token for timer handler used to check
  90.                  * up on target during long sends. */
  91.     Tcl_Interp *interp;        /* Interpreter from which the send
  92.                  * was invoked. */
  93.     int code;            /* Tcl return code for command
  94.                  * will be stored here. */
  95.     char *result;        /* String result for command (malloc'ed),
  96.                  * or NULL. */
  97.     char *errorInfo;        /* Information for "errorInfo" variable,
  98.                  * or NULL (malloc'ed). */
  99.     char *errorCode;        /* Information for "errorCode" variable,
  100.                  * or NULL (malloc'ed). */
  101.     int gotResponse;        /* 1 means a response has been received,
  102.                  * 0 means the command is still outstanding. */
  103.     struct PendingCommand *nextPtr;
  104.        /* Next in list of all outstanding
  105.     * commands.  NULL means end of
  106.     * list. */
  107. } PendingCommand;
  108.  
  109. static PendingCommand *pendingCommands = NULL;
  110. /* List of all commands currently
  111.  * being waited for. */
  112.  
  113.      /*
  114.       * The information below is used for communication between processes
  115.       * during "send" commands.  Each process keeps a private window, never
  116.       * even mapped, with one property, "Comm".  When a command is sent to
  117.       * an interpreter, the command is appended to the comm property of the
  118.       * communication window associated with the interp's process.  Similarly,
  119.       * when a result is returned from a sent command, it is also appended
  120.       * to the comm property.
  121.       *
  122.       * Each command and each result takes the form of ASCII text.  For a
  123.       * command, the text consists of a zero character followed by several
  124.       * null-terminated ASCII strings.  The first string consists of the
  125.       * single letter "c".  Subsequent strings have the form "option value"
  126.       * where the following options are supported:
  127.       *
  128.       * -r commWindow serial
  129.       *
  130.       *    This option means that a response should be sent to the window
  131.       *    whose X identifier is "commWindow" (in hex), and the response should
  132.       *    be identified with the serial number given by "serial" (in decimal).
  133.       *    If this option isn't specified then the send is asynchronous and
  134.       *    no response is sent.
  135.       *
  136.       * -n name
  137.       *    "Name" gives the name of the application for which the command is
  138.       *    intended.  This option must be present.
  139.       *
  140.       * -s script
  141.       *
  142.       *    "Script" is the script to be executed.  This option must be present.
  143.       *
  144.       * The options may appear in any order.  The -n and -s options must be
  145.       * present, but -r may be omitted for asynchronous RPCs.  For compatibility
  146.       * with future releases that may add new features, there may be additional
  147.       * options present;  as long as they start with a "-" character, they will
  148.       * be ignored.
  149.       *
  150.       * A result also consists of a zero character followed by several null-
  151.       * terminated ASCII strings.  The first string consists of the single
  152.       * letter "r".  Subsequent strings have the form "option value" where
  153.       * the following options are supported:
  154.       *
  155.       * -s serial
  156.       *
  157.       *    Identifies the command for which this is the result.  It is the
  158.       *    same as the "serial" field from the -s option in the command.  This
  159.       *    option must be present.
  160.       *
  161.       * -c code
  162.       *
  163.       *    "Code" is the completion code for the script, in decimal.  If the
  164.       *    code is omitted it defaults to TCL_OK.
  165.       *
  166.       * -r result
  167.       *
  168.       *    "Result" is the result string for the script, which may be either
  169.       *    a result or an error message.  If this field is omitted then it
  170.       *    defaults to an empty string.
  171.       *
  172.       * -i errorInfo
  173.       *
  174.       *    "ErrorInfo" gives a string with which to initialize the errorInfo
  175.       *    variable.  This option may be omitted;  it is ignored unless the
  176.       *    completion code is TCL_ERROR.
  177.       *
  178.       * -e errorCode
  179.       *
  180.       *    "ErrorCode" gives a string with with to initialize the errorCode
  181.       *    variable.  This option may be omitted;  it is ignored  unless the
  182.       *    completion code is TCL_ERROR.
  183.       *
  184.       * Options may appear in any order, and only the -s option must be
  185.       * present.  As with commands, there may be additional options besides
  186.       * these;  unknown options are ignored.
  187.       */
  188.  
  189.      /*
  190.       * The following variable is the serial number that was used in the
  191.       * last "send" command.  It is exported only for testing purposes.
  192.       */
  193.  
  194. int tkSendSerial = 0;
  195.  
  196.      /*
  197.       * Maximum size property that can be read at one time by
  198.       * this module:
  199.       */
  200.  
  201. #define MAX_PROP_WORDS 100000
  202.  
  203. /*
  204.  * Forward declarations for procedures defined later in this file:
  205.  */
  206.  
  207. static int        AppendErrorProc _ANSI_ARGS_((ClientData clientData,
  208.                 XErrorEvent *errorPtr));
  209. static void        AppendPropCarefully _ANSI_ARGS_((Display *display,
  210.                  Window window, Atom property, char *value,
  211.                  int length, PendingCommand *pendingPtr));
  212. static void        DeleteProc _ANSI_ARGS_((ClientData clientData));
  213. static void        RegAddName _ANSI_ARGS_((NameRegistry *regPtr,
  214.                 char *name, Window commWindow));
  215. static void        RegClose _ANSI_ARGS_((NameRegistry *regPtr));
  216. static void        RegDeleteName _ANSI_ARGS_((NameRegistry *regPtr,
  217.                           char *name));
  218. static Window        RegFindName _ANSI_ARGS_((NameRegistry *regPtr,
  219.                 char *name));
  220. static NameRegistry *    RegOpen _ANSI_ARGS_((Tcl_Interp *interp,
  221.                  TkWindow *winPtr, int lock));
  222. static void        SendEventProc _ANSI_ARGS_((ClientData clientData,
  223.                                XEvent *eventPtr));
  224. static int        SendInit _ANSI_ARGS_((Tcl_Interp *interp,
  225.                   TkWindow *winPtr));
  226. static Bool        SendRestrictProc _ANSI_ARGS_((Display *display,
  227.                   XEvent *eventPtr, char *arg));
  228. static int        ServerSecure _ANSI_ARGS_((TkDisplay *dispPtr));
  229. static void        TimeoutProc _ANSI_ARGS_((ClientData clientData));
  230. static int        ValidateName _ANSI_ARGS_((TkDisplay *dispPtr,
  231.                  char *name, Window commWindow, int oldOK));
  232.  
  233. /*
  234.  *--------------------------------------------------------------
  235.  *
  236.  * Tk_SetAppName --
  237.  *
  238.  *    This procedure is called to associate an ASCII name with a Tk
  239.  *    application.  If the application has already been named, the
  240.  *    name replaces the old one.
  241.  *
  242.  * Results:
  243.  *    The return value is the name actually given to the application.
  244.  *    This will normally be the same as name, but if name was already
  245.  *    in use for an application then a name of the form "name #2" will
  246.  *    be chosen,  with a high enough number to make the name unique.
  247.  *
  248.  * Side effects:
  249.  *    Registration info is saved, thereby allowing the "send" command
  250.  *    to be used later to invoke commands in the application.  In
  251.  *    addition, the "send" command is created in the application's
  252.  *    interpreter.  The registration will be removed automatically
  253.  *    if the interpreter is deleted or the "send" command is removed.
  254.  *
  255.  *--------------------------------------------------------------
  256.  */
  257.  
  258. char *
  259. Tk_SetAppName(
  260.     Tk_Window tkwin,        /* Token for any window in the application
  261.                  * to be named:  it is just used to identify
  262.                  * the application and the display.  */
  263.     char *name)            /* The name that will be used to
  264.                  * refer to the interpreter in later
  265.                  * "send" commands.  Must be globally
  266.                  * unique. */
  267. {
  268.     return name;
  269. }
  270.  
  271. /*
  272.  *--------------------------------------------------------------
  273.  *
  274.  * Tk_SendCmd --
  275.  *
  276.  *    This procedure is invoked to process the "send" Tcl command.
  277.  *    See the user documentation for details on what it does.
  278.  *
  279.  * Results:
  280.  *    A standard Tcl result.
  281.  *
  282.  * Side effects:
  283.  *    See the user documentation.
  284.  *
  285.  *--------------------------------------------------------------
  286.  */
  287.  
  288. int
  289. Tk_SendCmd(
  290.     ClientData clientData,        /* Information about sender (only
  291.                      * dispPtr field is used). */
  292.     Tcl_Interp *interp,            /* Current interpreter. */
  293.     int argc,                /* Number of arguments. */
  294.     char **argv)            /* Argument strings. */
  295. {
  296.     Tcl_SetResult(interp, "Send not yet implemented", TCL_STATIC);
  297.     return TCL_ERROR;
  298. }
  299.  
  300. /*
  301.  *----------------------------------------------------------------------
  302.  *
  303.  * TkGetInterpNames --
  304.  *
  305.  *    This procedure is invoked to fetch a list of all the
  306.  *    interpreter names currently registered for the display
  307.  *    of a particular window.
  308.  *
  309.  * Results:
  310.  *    A standard Tcl return value.  Interp->result will be set
  311.  *    to hold a list of all the interpreter names defined for
  312.  *    tkwin's display.  If an error occurs, then TCL_ERROR
  313.  *    is returned and interp->result will hold an error message.
  314.  *
  315.  * Side effects:
  316.  *    None.
  317.  *
  318.  *----------------------------------------------------------------------
  319.  */
  320.  
  321. int
  322. TkGetInterpNames(
  323.     Tcl_Interp *interp,        /* Interpreter for returning a result. */
  324.     Tk_Window tkwin)        /* Window whose display is to be used
  325.                  * for the lookup. */
  326. {
  327.     Tcl_SetResult(interp, "Send not yet implemented", TCL_STATIC);
  328.     return TCL_ERROR;
  329. }
  330.  
  331. /*
  332.  *--------------------------------------------------------------
  333.  *
  334.  * SendInit --
  335.  *
  336.  *    This procedure is called to initialize the
  337.  *    communication channels for sending commands and
  338.  *    receiving results.
  339.  *
  340.  * Results:
  341.  *    None.
  342.  *
  343.  * Side effects:
  344.  *    Sets up various data structures and windows.
  345.  *
  346.  *--------------------------------------------------------------
  347.  */
  348.  
  349. static int
  350. SendInit(
  351.     Tcl_Interp *interp,        /* Interpreter to use for error reporting
  352.                  * (no errors are ever returned, but the
  353.                  * interpreter is needed anyway). */
  354.     TkWindow *winPtr)        /* Window that identifies the display to
  355.                  * initialize. */
  356. {
  357.     return TCL_OK;
  358. }
  359.